﻿using Microsoft.EntityFrameworkCore;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization;

namespace DDD.Domain
{
    [Index(nameof(IsDeleted))]
    public abstract class Entity : IEntity
    {
        [Required]
        [Column(Order = 1)]
        public bool IsDeleted { get; protected set; } = false;

        [Timestamp]
        public byte[] RowVersion { get; set; }

        public abstract object[] GetKey();

        public override string ToString()
        {
            return $"[Entity:{this.GetType().Name};Keys:{string.Join(",", this.GetKey())}]";
        }

        public virtual void Delete()
        {
            this.IsDeleted = true;
        }

        #region 事件
        private Collection<IDomainEvent> domainEvents = new Collection<IDomainEvent>();
        [NotMapped]
        [JsonIgnore]
        public IReadOnlyCollection<IDomainEvent> DomainEvents => domainEvents.AsReadOnly();


        public void AddDomainEvent(IDomainEvent item)
        {
            domainEvents.Add(item);
        }
        public void RemoveDomainEvent(IDomainEvent item)
        {
            domainEvents.Remove(item);
        }
        public void ClearDomainEvent()
        {
            domainEvents.Clear();
        }
        #endregion
    }

    public abstract class Entity<TKey> : Entity, IEntity<TKey>
    {

        [Key]
        [Column(Order = 0)]
        public virtual  TKey Id { get; set; }

        public override object[] GetKey()
        {
            return new object[] { Id };
        }

        public override string ToString()
        {
            return $"[Entity:{this.GetType().Name};Keys:{string.Join(",", this.GetKey())}]";
        }

        public bool IsTransiented()
        {
            return EqualityComparer<TKey>.Default.Equals(Id, default(TKey));
        }

        //public override int GetHashCode()
        //{
        //    if (IsTransiented())
        //    {
        //        return base.GetHashCode();
        //    }

        //    return Id.GetHashCode() ^ 31;
        //}

        //public override bool Equals([AllowNull] object obj)
        //{
        //    if (obj == null)
        //    {
        //        return false;
        //    }

        //    if (obj is Entity<TKey> == false)
        //    {
        //        return false;
        //    }

        //    if (obj.GetType() != this.GetType())
        //    {
        //        return false;
        //    }

        //    if (Object.ReferenceEquals(this, obj))
        //    {
        //        return true;
        //    }


        //    Entity<TKey> other = (Entity<TKey>)obj;
        //    if (other.IsTransiented() || this.IsTransiented())
        //    {
        //        return false;
        //    }
        //    return other.Id.Equals(this.Id);

        //    //return base.Equals(obj);
        //}


        //public static bool operator ==(Entity<TKey> left, Entity<TKey> right) { return left.Equals(right); }
        //public static bool operator !=(Entity<TKey> left, Entity<TKey> right) { return !left.Equals(right); }
    }

}
